<template>
  <div class="upload-container" 
       @click="handleClick" 
       @dragover.prevent="handleDragOver" 
       @dragleave="handleDragLeave"
       @drop.prevent="handleDrop" 
       :class="{ 'drag-active': isDragActive }">
    <input type="file" 
           ref="fileInput" 
           @change="handleFileChange" 
           style="display: none" 
           :multiple="multiple"
           :accept="accept">

    <div class="upload-content">
      <slot>
        <div class="default-content">
          <SvgIcon :svg="svgUpload" :size="45" class="upload-icon" />
          <p>点击或拖拽文件到此处上传</p>
          <p class="hint-text" v-if="hint">{{ hint }}</p>
        </div>
      </slot>
    </div>
    <!-- <div class="file-list" v-if="showFileList && modelValue.length">
      <div class="file-item" v-for="(file, index) in modelValue" :key="file.name + index">
        <span>{{ file.name }}</span>
        <span class="file-size">({{ formatFileSize(file.size) }})</span>
        <span class="delete-icon" @click.stop="handleRemove(index)">×</span>
      </div>
    </div> -->
  </div>
</template>

<script setup>
import { ref } from 'vue'
import svgUpload from '@/assets/svg/upload.svg?raw'
const props = defineProps({
  modelValue: {
    type: Array,
    default: () => []
  },
  multiple: {
    type: Boolean,
    default: false
  },
  accept: {
    type: String,
    default: ''
  },
  maxSize: {
    type: Number,
    default: 0 // 0表示不限制
  },
  showFileList: {
    type: Boolean,
    default: true
  },
  hint: {
    type: String,
    default: ''
  }
})

const emit = defineEmits(['update:modelValue', 'change', 'error'])

const fileInput = ref(null)
const isDragActive = ref(false)

const handleClick = () => {
  fileInput.value.click()
}

const handleDragOver = () => {
  isDragActive.value = true
}

const handleDragLeave = () => {
  isDragActive.value = false
}

const handleDrop = (e) => {
  isDragActive.value = false
  const files = e.dataTransfer.files
  if (files.length) {
    processFiles(files)
  }
}

const handleFileChange = (e) => {
  const files = e.target.files
  if (files.length) {
    processFiles(files)
  }
  // 清空input值，允许重复选择同一文件
  e.target.value = ''
}

const processFiles = (files) => {
  const newFiles = Array.from(files)

  // 检查文件类型
  if (props.accept) {
    const acceptTypes = props.accept.split(',').map(type => type.trim())
    const invalidFiles = newFiles.filter(file => {
      return !acceptTypes.some(type => {
        return file.type.match(type.replace('*', '.*')) ||
          file.name.toLowerCase().endsWith(type.replace('*', '').toLowerCase())
      })
    })

    if (invalidFiles.length) {
      emit('error', '文件类型不符合要求')
      return
    }
  }

  // 检查文件大小
  if (props.maxSize > 0) {
    const oversizedFiles = newFiles.filter(file => file.size > props.maxSize * 1024 * 1024)
    if (oversizedFiles.length) {
      emit('error', `文件大小不能超过${props.maxSize}MB`)
      return
    }
  }

  // 处理多选/单选
  let resultFiles = []
  if (props.multiple) {
    resultFiles = [...props.modelValue, ...newFiles]
  } else {
    resultFiles = newFiles.slice(0, 1)
  }

  emit('update:modelValue', resultFiles)
  emit('change', resultFiles)
}

const handleRemove = (index) => {
  const newFiles = [...props.modelValue]
  newFiles.splice(index, 1)
  emit('update:modelValue', newFiles)
  emit('change', newFiles)
}

const formatFileSize = (bytes) => {
  if (bytes === 0) return '0 Bytes'
  const k = 1024
  const sizes = ['Bytes', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}
</script>

<style scoped>
.upload-container {
  border: 2px dashed #d9d9d9;
  border-radius: 6px;
  padding: 20px;
  text-align: center;
  cursor: pointer;
  transition: border-color 0.3s;
  position: relative;
}

.upload-container:hover,
.drag-active {
  border-color: #409eff;
}

.upload-content {
  color: #606266;
}

.upload-icon {
  font-size: 48px;
  color: #c0c4cc;
  margin-bottom: 16px;
}

.hint-text {
  font-size: 12px;
  color: #909399;
  margin-top: 8px;
}

.file-list {
  margin-top: 16px;
  text-align: left;
}

.file-item {
  display: flex;
  align-items: center;
  padding: 8px;
  border-radius: 4px;
  background-color: #f5f7fa;
  margin-bottom: 8px;
}

.file-size {
  color: #909399;
  margin-left: 8px;
  font-size: 12px;
}

.delete-icon {
  margin-left: auto;
  color: #f56c6c;
  cursor: pointer;
  font-size: 16px;
}
</style>